import asyncio
from playwright.async_api import async_playwright
from dotenv import load_dotenv
from sqlalchemy.orm import Session
import json
import os
import logging

# 尝试修复httpx代理问题
try:
    import httpx
    
    # 检查是否需要进行monkey patch
    original_client = httpx.Client
    test_client_args = {'proxies': None}
    try:
        # 尝试创建带有proxies参数的客户端
        test_client = original_client(**test_client_args)
        logging.info("httpx.Client支持proxies参数，无需修复")
    except TypeError:
        logging.warning("检测到httpx.Client不支持proxies参数，应用monkey patch")
        
        # 定义不接受proxies参数的Client类
        class ClientWithoutProxies(original_client):
            def __init__(self, **kwargs):
                if 'proxies' in kwargs:
                    logging.info("拦截并移除了proxies参数")
                    del kwargs['proxies']
                super().__init__(**kwargs)
        
        # 替换httpx.Client
        httpx.Client = ClientWithoutProxies
        
        # 同样处理AsyncClient
        original_async_client = httpx.AsyncClient
        
        class AsyncClientWithoutProxies(original_async_client):
            def __init__(self, **kwargs):
                if 'proxies' in kwargs:
                    logging.info("拦截并移除了异步客户端的proxies参数")
                    del kwargs['proxies']
                super().__init__(**kwargs)
        
        # 替换httpx.AsyncClient
        httpx.AsyncClient = AsyncClientWithoutProxies
        
        logging.info("成功应用httpx客户端monkey patch")
except Exception as e:
    logging.warning(f"应用httpx代理问题修复失败: {str(e)}")

from openai import AsyncOpenAI
from typing import Dict, Any, Optional

load_dotenv()

class BrowserAgent:
    def __init__(self, task_id: int, task_type: str, url: str, model: str, db: Optional[Session] = None, script: Optional[str] = None):
        self.task_id = task_id
        self.task_type = task_type
        self.url = url
        
        # 获取API密钥和模型设置
        api_key = None
        api_base_url = "https://api.deepseek.com"
        
        # 如果提供了数据库会话，尝试从数据库系统配置中读取
        if db:
            try:
                from backend.data_clean.models import SystemConfig
                api_key_config = db.query(SystemConfig).filter(SystemConfig.key == "DEEPSEEK_API_KEY").first()
                if api_key_config and api_key_config.value:
                    api_key = api_key_config.value
                
                # 获取API基础URL
                base_url_config = db.query(SystemConfig).filter(SystemConfig.key == "DEEPSEEK_API_URL").first()
                if base_url_config and base_url_config.value:
                    # 从完整API URL中提取基础URL部分
                    api_url = base_url_config.value
                    if api_url:
                        parts = api_url.split("/v1/")
                        if len(parts) > 1:
                            api_base_url = parts[0]
                
                # 获取模型
                model_config = db.query(SystemConfig).filter(SystemConfig.key == "DEEPSEEK_MODEL").first()
                if model_config and model_config.value:
                    self.model = model_config.value
                else:
                    self.model = model or "deepseek-chat"
            except Exception as e:
                print(f"从数据库获取API配置失败: {str(e)}")
        
        # 如果数据库中没有找到，则使用环境变量或默认值
        if not api_key:
            api_key = os.getenv("DEEPSEEK_API_KEY")
        
        if not self.model:
            self.model = os.getenv("DEEPSEEK_MODEL", "deepseek-chat")
            
        self.script = script
        self.browser = None
        self.page = None
        
        # 初始化API客户端
        self.client = AsyncOpenAI(
            api_key=api_key,
            base_url=api_base_url
        )
        
        self.logs = []

    async def chat_completion(self, prompt: str) -> str:
        try:
            response = await self.client.chat.completions.create(
                model=self.model,
                messages=[
                    {"role": "system", "content": "你是一个专业的浏览器自动化助手，可以帮助分析网页内容并提供操作建议。"},
                    {"role": "user", "content": prompt}
                ],
                stream=False
            )
            return response.choices[0].message.content
        except Exception as e:
            await self.log("error", f"AI API调用失败: {str(e)}")
            raise

    async def setup(self):
        # 初始化浏览器
        playwright = await async_playwright().start()
        self.browser = await playwright.chromium.launch(headless=True)
        self.page = await self.browser.new_page()

    async def log(self, level: str, message: str):
        self.logs.append({
            "task_id": self.task_id,
            "level": level,
            "message": message
        })

    async def execute_web_task(self) -> Dict[str, Any]:
        await self.log("info", f"开始执行网页操作任务: {self.url}")
        
        try:
            await self.page.goto(self.url)
            await self.log("info", "页面加载完成")

            # 获取页面内容
            content = await self.page.content()
            
            # 使用 AI 分析页面内容并生成操作步骤
            response = await self.chat_completion(
                f"""分析以下网页内容，并生成操作步骤：

页面URL: {self.url}
页面内容: {content[:2000]}...

请生成具体的操作步骤，包括：
1. 需要点击的元素
2. 需要填写的表单
3. 需要执行的操作
"""
            )

            await self.log("info", f"AI分析结果: {response}")
            
            # 执行 AI 生成的操作步骤
            steps = response.split("\n")
            for step in steps:
                if step.strip():
                    await self.log("info", f"执行步骤: {step}")
                    # TODO: 实现具体的操作步骤执行逻辑

            return {
                "status": "success",
                "steps": steps,
                "result": "任务执行完成"
            }

        except Exception as e:
            await self.log("error", f"执行任务失败: {str(e)}")
            return {
                "status": "error",
                "error": str(e)
            }

    async def execute_form_task(self) -> Dict[str, Any]:
        await self.log("info", f"开始执行表单填写任务: {self.url}")
        
        try:
            await self.page.goto(self.url)
            await self.log("info", "页面加载完成")

            # 获取表单信息
            forms = await self.page.query_selector_all("form")
            form_data = []
            
            for form in forms:
                inputs = await form.query_selector_all("input, select, textarea")
                form_info = []
                
                for input_el in inputs:
                    input_type = await input_el.get_attribute("type") or "text"
                    input_name = await input_el.get_attribute("name")
                    input_id = await input_el.get_attribute("id")
                    
                    form_info.append({
                        "type": input_type,
                        "name": input_name,
                        "id": input_id
                    })
                
                form_data.append(form_info)

            # 使用 AI 分析表单并生成填写策略
            response = await self.chat_completion(
                f"""分析以下表单信息，并生成填写策略：

表单数据: {json.dumps(form_data, indent=2)}

请生成表单填写策略，包括：
1. 每个字段应该填写的值
2. 特殊字段的处理方法
3. 提交表单的方式
"""
            )

            await self.log("info", f"AI分析结果: {response}")
            
            # TODO: 实现表单填写逻辑

            return {
                "status": "success",
                "form_data": form_data,
                "strategy": response
            }

        except Exception as e:
            await self.log("error", f"执行任务失败: {str(e)}")
            return {
                "status": "error",
                "error": str(e)
            }

    async def execute_scraping_task(self) -> Dict[str, Any]:
        await self.log("info", f"开始执行数据采集任务: {self.url}")
        
        try:
            await self.page.goto(self.url)
            await self.log("info", "页面加载完成")

            # 获取页面内容
            content = await self.page.content()
            
            # 使用 AI 分析页面内容并确定数据采集策略
            response = await self.chat_completion(
                f"""分析以下网页内容，并确定数据采集策略：

页面URL: {self.url}
页面内容: {content[:2000]}...

请确定：
1. 需要采集的数据类型
2. 数据所在的HTML元素
3. 数据提取方法
"""
            )

            await self.log("info", f"AI分析结果: {response}")
            
            # TODO: 实现数据采集逻辑

            return {
                "status": "success",
                "strategy": response,
                "data": []  # 采集到的数据
            }

        except Exception as e:
            await self.log("error", f"执行任务失败: {str(e)}")
            return {
                "status": "error",
                "error": str(e)
            }

    async def execute_custom_script(self) -> Dict[str, Any]:
        await self.log("info", "开始执行自定义脚本任务")
        
        try:
            if not self.script:
                raise ValueError("未提供自定义脚本")

            # 使用 AI 分析脚本并提供执行建议
            response = await self.chat_completion(
                f"""分析以下Python脚本，并提供执行建议：

脚本内容:
{self.script}

请提供：
1. 脚本的主要功能
2. 可能的风险点
3. 执行建议
"""
            )

            await self.log("info", f"AI分析结果: {response}")
            
            # TODO: 实现安全的脚本执行环境

            return {
                "status": "success",
                "analysis": response
            }

        except Exception as e:
            await self.log("error", f"执行任务失败: {str(e)}")
            return {
                "status": "error",
                "error": str(e)
            }

    async def execute(self) -> Dict[str, Any]:
        await self.setup()
        
        try:
            if self.task_type == "web":
                result = await self.execute_web_task()
            elif self.task_type == "form":
                result = await self.execute_form_task()
            elif self.task_type == "scraping":
                result = await self.execute_scraping_task()
            elif self.task_type == "custom":
                result = await self.execute_custom_script()
            else:
                raise ValueError(f"不支持的任务类型: {self.task_type}")

            return {
                "success": True,
                "result": result,
                "logs": self.logs
            }

        except Exception as e:
            await self.log("error", f"任务执行失败: {str(e)}")
            return {
                "success": False,
                "error": str(e),
                "logs": self.logs
            }

        finally:
            if self.browser:
                await self.browser.close()

    @classmethod
    async def create_and_execute(cls, task_id: int, task_type: str, url: str, model: str, db: Optional[Session] = None, script: Optional[str] = None) -> Dict[str, Any]:
        agent = cls(task_id, task_type, url, model, db, script)
        return await agent.execute() 